package main

import (
	"fmt"
)

// Programmer 接口是一个协议-程序员-只要你能够1.写代码 2.解决bug 其实就是一组方法的
// Programmer 类型只是一个抽象的类型，不能具体的进行实例化。只能用一个具体的类型来进行实例化
type Programmer interface {
	Coding() string //方法只是申明
	Debug() string
}

type Designer interface {
	Design() string
}
type Manger interface {
	Programmer
	Designer
	Manage() string
}
type UIDesigner struct {
}

type MyError struct {
}

func (m MyError) Error() string {
	fmt.Println("出错了")
	return "出错了"
}

func (d UIDesigner) Design() string {
	fmt.Println("我会ui设计")
	return "我会ui设计"
}

//  Python java的话 java里面一种类型只要继承一个接口 才行 如果你继承了这个接口的话，那么这个接口里面所有的方法你必须要全部实现
type Pythoner struct {
	UIDesigner
	lib  []string
	kj   []string
	year int
}
type Goer struct {
}

func (p Goer) Coding() string {
	fmt.Println("go开发者")
	return "go开发者"
}

func (p Goer) Debug() string {
	fmt.Println("我会go的debug")
	return "我会go的debug"
}

func (p Pythoner) Coding() string {
	fmt.Println("python开发者")
	return "python开发"
}

func (p Pythoner) Debug() string {
	fmt.Println("我会python的debug")
	return "我会python的debug"
}
func (p Pythoner) Manage() string {
	fmt.Println("我会python的Manage")
	return "我会python的Manage"
}

func (p Pythoner) Design() string {
	fmt.Println("我会python的Design")
	return "我会python的Design"
}

//对于Pythoner这个结构体来说 你实现任何方法都可以，但是你只要不全部实现coding Debug的话 那你pythoner就不是一个Programmer类型
//1.pythoner本身自己就是一个类型 那我何必在意我是不是Programmer
//2. 1封装 继承 多态-多态的概念对于很多python开发者来说会有点陌生
//3.在讲解多态之前  我们来对interface 做一个说明：在go语言中接口是一种类型, int 是一种抽象类型
func main() {
	var pro Programmer = Pythoner{}
	pro.Coding()
	var pros []Programmer
	pros = append(pros, Pythoner{})
	pros = append(pros, Goer{})
	fmt.Println(pros)

	//接口虽然是一种类型 但是和其他类型不太一样 接口是一种抽象类型 struct是具象的
	p := Pythoner{}
	fmt.Printf("%T\n", p)
	var pro1 Programmer = Pythoner{}
	fmt.Printf("%T\n", pro1)
	var pro2 Programmer = Goer{}
	fmt.Printf("%T\n", pro2)

	//1.go struct的组合一起实现了所有的接口的方法是可以的
	//2.接口本身也支持组合
	var manager Manger = Pythoner{}
	manager.Manage()
	manager.Design()
	// struct 组合完成了接口
	// 1.接口支持组合--继承
	//2.结构体组合实现了所有的接口方法也没有问题
	//var err error = MyError{}
	//err.Error()
	s := "文件不存在"
	var err error = fmt.Errorf("错误:%s", s)
	fmt.Println(err)
}
